//#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/syscall_barrier.h>
//#include <linux/init.h>
//#include <linux/wait.h>


extern spinlock_t g_lock;
extern struct list_head g_blist;

asmlinkage long sys_barrierdestroy(int barrierID) {
  barrier_data_t *t_bl;
	struct list_head *pos, *q;
	
	spin_lock(&g_lock);
	
	list_for_each_safe(pos, q, &g_blist) {
		t_bl = list_entry(pos, barrier_data_t, b_list_elem);
		spin_lock(&(t_bl->barrier_lock));//lock barrier
		int t_rc = atomic_read(&t_bl->ref_count);
		if(atomic_read(&t_bl->ID) == barrierID) {//if barrier exists - wake all processes and kill and remove
			//wake up all processes
			if(t_rc!=atomic_read(&t_bl->N))
			{
				t_rc=-1;
			}
			wake_up_all(&(t_bl->wq_head));
			
			spin_unlock(&(t_bl->barrier_lock));//release barrier_lock
			list_del(pos);//remove barrier from list
			spin_unlock(&g_lock);//release g_blist
			kfree(t_bl);
			return t_rc;
		}
		spin_unlock(&(t_bl->barrier_lock));//release barrier_lock
		if (pos->next == &g_blist) {
			//release lock
			spin_unlock(&g_lock);//release g_blist
			kfree(t_bl);
			return -1;
		}
	}
	spin_unlock(&g_lock);//release g_blist
	return -1;
}
